package com.bing.bingPro.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bing.bingPro.DateUtils;
import com.bing.bingPro.controller.dto.TNetDto;
import com.bing.bingPro.controller.dto.TOrderDateDTO;
import com.bing.bingPro.controller.dto.zTrendDto;
import com.bing.bingPro.controller.vo.TNetworkTopologyPonAreaDayVo;
import com.bing.bingPro.controller.vo.zRankVo;
import com.bing.bingPro.controller.vo.zTrendVo;
import com.bing.bingPro.entity.DZoneInfoIpv6;
import com.bing.bingPro.entity.TNetworkTopologyPonAreaDay;
import com.bing.bingPro.enums.TimeGranularityEnums;
import com.bing.bingPro.mapper.DZoneInfoIpv6Mapper;
import com.bing.bingPro.mapper.TNetworkTopologyPonAreaDayMapper;
import com.bing.bingPro.service.DZoneInfoIpv6Service;
import com.bing.bingPro.service.DZoneInfoService;
import com.bing.bingPro.service.TNetworkTopologyPonAreaDayService;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 29821
 * @description 针对表【t_network_topology_pon_area_day】的数据库操作Service实现
 * @createDate 2023-07-10 09:53:23
 */
@Slf4j
@Service
public class TNetworkTopologyPonAreaDayServiceImpl extends ServiceImpl<TNetworkTopologyPonAreaDayMapper, TNetworkTopologyPonAreaDay>
        implements TNetworkTopologyPonAreaDayService {


    @Resource
    private TNetworkTopologyPonAreaDayMapper tNetworkTopologyPonAreaDayMapper;

    @Resource
    private DZoneInfoService dZoneInfoService;
    @Resource
    private DZoneInfoIpv6Service dZoneInfoIpv6Service;

    @Resource
    private DZoneInfoIpv6Mapper dZoneInfoIpv6Mapper;

    @SuppressWarnings("unchecked")
    @Override
    public List<Map<String, Object>> getCity() {
        List<TNetworkTopologyPonAreaDay> tNetworkTopologyPonAreaDayList = tNetworkTopologyPonAreaDayMapper.selectList(Wrappers.lambdaQuery(TNetworkTopologyPonAreaDay.class)
                .select(TNetworkTopologyPonAreaDay::getProvinceName, TNetworkTopologyPonAreaDay::getCityName, TNetworkTopologyPonAreaDay::getRegionName)
                .groupBy(TNetworkTopologyPonAreaDay::getProvinceName, TNetworkTopologyPonAreaDay::getCityName, TNetworkTopologyPonAreaDay::getRegionName));
        Map<String, Map<String, List<Map<String, String>>>> resultMap = tNetworkTopologyPonAreaDayList.stream()
                .collect(Collectors.groupingBy(TNetworkTopologyPonAreaDay::getProvinceName,
                        LinkedHashMap::new,
                        Collectors.groupingBy(TNetworkTopologyPonAreaDay::getCityName,
                                LinkedHashMap::new,
                                Collectors.mapping(recordName -> {
                                    Map<String, String> regionMap = new HashMap<>();
                                    regionMap.put("name", recordName.getRegionName());
                                    return regionMap;
                                }, Collectors.toList()))));

        List<Map<String, Object>> finalList = new ArrayList<>();
        Map<String, Object> countryMap = new LinkedHashMap<>();
        countryMap.put("name", "全国");
        finalList.add(countryMap);

        resultMap.forEach((provinceName, cityMap) -> {
            Map<String, Object> provinceCityMap = new LinkedHashMap<>();
            provinceCityMap.put("name", provinceName);

            List<Map<String, Object>> innerCityArray = new ArrayList<>();
            cityMap.forEach((cityName, regionList) -> {
                Map<String, Object> city = new LinkedHashMap<>();
                city.put("name", cityName);
                city.put("children", regionList);
                innerCityArray.add(city);
            });

            provinceCityMap.put("children", innerCityArray);
            finalList.add(provinceCityMap);
        });
        return finalList;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<String> dateList(TOrderDateDTO tOrderDateDTO) {
        List<String> dateTimeList;
        if ("0".equals(tOrderDateDTO.getTimeGranularity())) {
            dateTimeList = tNetworkTopologyPonAreaDayMapper.dateDay().stream()
                    .map(date -> date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                    .sorted(Comparator.reverseOrder())
                    .collect(Collectors.toList());
            return dateTimeList;
        } else if ("2".equals(tOrderDateDTO.getTimeGranularity())) {
            dateTimeList = tNetworkTopologyPonAreaDayMapper.selectList(
                            Wrappers.lambdaQuery(TNetworkTopologyPonAreaDay.class)
                                    .select(TNetworkTopologyPonAreaDay::getDataMonth)
                                    .groupBy(TNetworkTopologyPonAreaDay::getDataMonth)
                                    .orderByDesc(TNetworkTopologyPonAreaDay::getDataMonth)
                    )
                    .stream()
                    .map(TNetworkTopologyPonAreaDay::getDataMonth)
                    .distinct()
                    .sorted(Comparator.reverseOrder())
                    .map(month -> month.substring(0, 4))
                    .collect(Collectors.toList());
            return dateTimeList;
        }
        dateTimeList = tNetworkTopologyPonAreaDayMapper.selectList(
                        Wrappers.lambdaQuery(TNetworkTopologyPonAreaDay.class)
                                .select(TNetworkTopologyPonAreaDay::getDataMonth)
                                .groupBy(TNetworkTopologyPonAreaDay::getDataMonth)
                                .orderByDesc(TNetworkTopologyPonAreaDay::getDataMonth)
                )
                .stream()
                .map(TNetworkTopologyPonAreaDay::getDataMonth)
                .distinct()
                .sorted(Comparator.reverseOrder())
                .map(month -> {
                    LocalDate date = LocalDate.parse(month + "01", DateTimeFormatter.ofPattern("yyyyMMdd"));
                    return date.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                })
                .collect(Collectors.toList());
        return dateTimeList;
    }

    @Override
    public List<TNetworkTopologyPonAreaDayVo> getDetail(TNetDto tOrderDateDTO) {
        Integer threshold = tOrderDateDTO.getThreshold();
        String province = getKeyProvince(tOrderDateDTO.getProvince());
        String time = tOrderDateDTO.getTime();
        String city = tOrderDateDTO.getCity();
        String region = tOrderDateDTO.getRegion();
        //时间粒度为日
        if (Objects.equals(TimeGranularityEnums.DAY.getCode(), tOrderDateDTO.getTimeGranularity())) {
            return baseMapper.getDayDetail(province, time, threshold, city, region);
        }
        //时间粒度为月
        String month = tOrderDateDTO.getTime().replace("-", "");
        return baseMapper.getMonthDetail(province, month, threshold, city, region);
    }


    @Override
    public List<zTrendVo> zTrend(zTrendDto zTrendDto) {
        List<zTrendVo> list = new ArrayList<>();
        Integer threshold = zTrendDto.getThreshold();
        String province = getKeyProvince(zTrendDto.getProvince());
        String city = Objects.isNull(zTrendDto.getCity()) ? "" : zTrendDto.getCity();
        String region = Objects.isNull(zTrendDto.getRegion()) ? "" : zTrendDto.getRegion();
        String time = zTrendDto.getTime();
        //时间粒度为日
        if (Objects.equals(TimeGranularityEnums.DAY.getCode(), zTrendDto.getTimeGranularity())) {
            long l = System.currentTimeMillis();
            List<zTrendVo> existingList = tNetworkTopologyPonAreaDayMapper.queryPonTrendList(threshold, time, province, city, region);
            long d = System.currentTimeMillis();
            log.info("sql耗时:"+(d-l)+"ms");
            Set<String> existingTimeStamps = existingList.stream()
                    .map(zTrendVo::getTime)
                    .collect(Collectors.toSet());

            List<String> monthFullDay = DateUtils.getMonthFullDay(Integer.parseInt(time.substring(0, 4)), Integer.parseInt(time.substring(5, 7)));
            List<String> missingTimeStamps = monthFullDay.stream()
                    .filter(timeStamp -> !existingTimeStamps.contains(timeStamp))
                    .collect(Collectors.toList());

            for (String dataTime : missingTimeStamps) {
                zTrendVo tBrasAndOltTrendDtoVo = new zTrendVo();
                tBrasAndOltTrendDtoVo.setTime(dataTime);
                list.add(tBrasAndOltTrendDtoVo);
            }

            list.addAll(existingList);
            list.sort(Comparator.comparingInt(o -> Integer.parseInt(o.getTime().replace("-", ""))));
            return list;
        }
        //时间粒度为月
        List<zTrendVo> existingData = tNetworkTopologyPonAreaDayMapper.queryPonTrendMonthList(threshold, time, province, city, region);
        for (zTrendVo tBrasAndOltTrendDtoVo : existingData) {
            Double outdoRateOne = tNetworkTopologyPonAreaDayMapper.queryPonTrendDayList
                    (threshold, tBrasAndOltTrendDtoVo.getTime().replace("-", ""), province, city, region);
            tBrasAndOltTrendDtoVo.setOverRunRate(outdoRateOne);
        }
        Set<String> existingMonths = existingData.stream().map(zTrendVo::getTime).collect(Collectors.toSet());
        List<zTrendVo> missingData = new ArrayList<>();
        int year = Integer.parseInt(zTrendDto.getTime());
        List<String> allMonths = DateUtils.getYearFullMonth(year);

        for (String month : allMonths) {
            if (!existingMonths.contains(month)) {
                zTrendVo tBrasAndOltTrendDtoVo = new zTrendVo();
                tBrasAndOltTrendDtoVo.setTime(month);
                missingData.add(tBrasAndOltTrendDtoVo);
            }
        }
        return Stream.concat(existingData.stream(), missingData.stream())
                .sorted(Comparator.comparingInt(o -> Integer.parseInt(o.getTime().replace("-", ""))))
                .collect(Collectors.toList());
    }

    @Override
    public List<zRankVo> zRank(zTrendDto zTrendDto) {
        List<zRankVo> list;
        Integer threshold = zTrendDto.getThreshold();
        String province = getKeyProvince(zTrendDto.getProvince());
        String city = Objects.isNull(zTrendDto.getCity()) ? "" : zTrendDto.getCity();
        String rankTime = zTrendDto.getSortDataTime();
        String time = zTrendDto.getSortDataTime().replace("-", "");
        //时间粒度为月
        if (rankTime.length() == 7) {
            list = tNetworkTopologyPonAreaDayMapper.queryPonRankMonthList(threshold, time, province, city);
            if (CharSequenceUtil.isEmpty(province)) {
                // 省份 日累计占比
                for (zRankVo tBrasAndOltSortDtoVo : list) {
                    if (Objects.isNull(tBrasAndOltSortDtoVo.getActivePONNum())) {
                        continue;
                    }
                    String provinceShort = dZoneInfoIpv6Mapper.selectMaps(
                            Wrappers.<DZoneInfoIpv6>lambdaQuery()
                                    .select(DZoneInfoIpv6::getProvinceShort)
                                    .eq(DZoneInfoIpv6::getProvinceName, tBrasAndOltSortDtoVo.getArea())
                                    .last("LIMIT 1")
                    ).get(0).get("province_short").toString();
                    Double aDouble = this.tNetworkTopologyPonAreaDayMapper.queryPonProvince(threshold, time, provinceShort);
                    tBrasAndOltSortDtoVo.setOverRunRate(aDouble);
                }
            } else if (CharSequenceUtil.isEmpty(city)) {
                // 地市 日累计占比
                for (zRankVo tBrasAndOltSortDtoVo : list) {
                    if (Objects.isNull(tBrasAndOltSortDtoVo.getActivePONNum())) {
                        continue;
                    }
                    Double aDouble = this.tNetworkTopologyPonAreaDayMapper.queryPonDayCity(threshold, time, province, tBrasAndOltSortDtoVo.getArea());
                    tBrasAndOltSortDtoVo.setOverRunRate(aDouble);
                }
            } else {
                // 区县 日累计占比
                for (zRankVo tBrasAndOltSortDtoVo : list) {
                    if (Objects.isNull(tBrasAndOltSortDtoVo.getActivePONNum())) {
                        continue;
                    }
                    Double aDouble = this.tNetworkTopologyPonAreaDayMapper.queryPonDayRegion(threshold, time, province, city, tBrasAndOltSortDtoVo.getArea());
                    tBrasAndOltSortDtoVo.setOverRunRate(aDouble);
                }
            }
        } else {
            //时间粒度为日
            long l = System.currentTimeMillis();
            list = tNetworkTopologyPonAreaDayMapper.queryPonDayOutdoStatSortList(threshold, rankTime, province, city);
            long d = System.currentTimeMillis();
            log.info("sql耗时:"+(d-l)+"ms");
        }
        Comparator<zRankVo> comparator;

        switch (zTrendDto.getRank()) {
            case "activePONNum":
                comparator = Comparator.comparingInt(o1 -> Objects.isNull(o1.getActivePONNum()) ? -1 : o1.getActivePONNum());
                break;
            case "overrunPONNum":
                comparator = Comparator.comparingInt(o1 -> Objects.isNull(o1.getOverrunPONNum()) ? -1 : o1.getOverrunPONNum());
                break;
            case "percentRate":
                comparator = Comparator.comparingDouble(o1 -> Objects.isNull(o1.getPercentRate()) ? -1 : o1.getPercentRate());
                break;
            default:
                comparator = Comparator.comparingDouble(o1 -> Objects.isNull(o1.getOverRunRate()) ? -1 : o1.getOverRunRate());
                break;
        }

        if ("desc".equals(zTrendDto.getSort())) {
            comparator = comparator.reversed();
        }

        list.sort(comparator);
        list.forEach(item -> {
            if (item.getPercentRate() != null) {
                BigDecimal bd = BigDecimal.valueOf(item.getPercentRate());
                bd = bd.setScale(4, RoundingMode.HALF_UP);
                item.setPercentRate(bd.doubleValue());
            }
        });
        return list;
    }

    @Override
    public PageInfo<TNetworkTopologyPonAreaDayVo> getDetailList(TNetDto tOrderDateDTO) {
        //获取配置阈值
        Integer threshold = tOrderDateDTO.getThreshold();
        String province = getKeyProvince(tOrderDateDTO.getProvince());
        String time = tOrderDateDTO.getTime();
        String city = tOrderDateDTO.getCity();
        String region = tOrderDateDTO.getRegion();
        Integer pageNum = tOrderDateDTO.getPageNum();
        Integer pageSize = tOrderDateDTO.getPageSize();
        //开启分页
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        PageMethod.startPage(pageNum, pageSize);
        //时间粒度为日
        if (Objects.equals(TimeGranularityEnums.DAY.getCode(), tOrderDateDTO.getTimeGranularity())) {
            List<TNetworkTopologyPonAreaDayVo> dayDetail = baseMapper.getDayDetail(province, time, threshold, city, region);
            return new PageInfo<>(dayDetail);
        }
        //时间粒度为月
        String month = tOrderDateDTO.getTime().replace("-", "");
        List<TNetworkTopologyPonAreaDayVo> monthDetail = baseMapper.getMonthDetail(province, month, threshold, city, region);
        return new PageInfo<>(monthDetail);
    }


    public static String getKeyProvince(String code) {
        final Map<String, String> provinceGetKeyMap = new LinkedHashMap<>();
        provinceGetKeyMap.put("安徽", "AH");
        provinceGetKeyMap.put("北京", "BJ");
        provinceGetKeyMap.put("重庆", "CQ");
        provinceGetKeyMap.put("福建", "FJ");
        provinceGetKeyMap.put("广东", "GD");
        provinceGetKeyMap.put("甘肃", "GS");
        provinceGetKeyMap.put("广西", "GX");
        provinceGetKeyMap.put("贵州", "GZ");
        provinceGetKeyMap.put("河南", "HA");
        provinceGetKeyMap.put("湖北", "HB");
        provinceGetKeyMap.put("河北", "HE");
        provinceGetKeyMap.put("海南", "HI");
        provinceGetKeyMap.put("黑龙江", "HL");
        provinceGetKeyMap.put("湖南", "HN");
        provinceGetKeyMap.put("吉林", "JL");
        provinceGetKeyMap.put("江苏", "JS");
        provinceGetKeyMap.put("江西", "JX");
        provinceGetKeyMap.put("辽宁", "LN");
        provinceGetKeyMap.put("内蒙古", "NM");
        provinceGetKeyMap.put("宁夏", "NX");
        provinceGetKeyMap.put("青海", "QH");
        provinceGetKeyMap.put("四川", "SC");
        provinceGetKeyMap.put("山东", "SD");
        provinceGetKeyMap.put("上海", "SH");
        provinceGetKeyMap.put("陕西", "SN");
        provinceGetKeyMap.put("山西", "SX");
        provinceGetKeyMap.put("天津", "TJ");
        provinceGetKeyMap.put("新疆", "XJ");
        provinceGetKeyMap.put("西藏", "XZ");
        provinceGetKeyMap.put("云南", "YN");
        provinceGetKeyMap.put("浙江", "ZJ");
        if (!provinceGetKeyMap.containsKey(code)) {
            return null;
        }
        return provinceGetKeyMap.get(code);
    }
}




